home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
mordor_2.000
/
mordor_2
/
src
/
files2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-29
|
18KB
|
736 lines
/*
* FILES2.C:
*
* Additional file routines, including memory management.
*
* Copyright (C) 1991, 1992, 1993 Brett J. Vickers
*
*/
#include "mstruct.h"
#include "mextern.h"
typedef struct queue_tag { /* General queue tag data struct */
int index;
struct queue_tag *next;
struct queue_tag *prev;
} qtag;
typedef struct rsparse { /* Sparse pointer array for rooms */
room *rom;
qtag *q_rom;
} rsparse;
typedef struct csparse { /* Sparse pointer array for creatures */
creature *crt;
qtag *q_crt;
} csparse;
typedef struct osparse { /* Sparse pointer array for objects */
object *obj;
qtag *q_obj;
} osparse;
static rsparse Rom[RMAX]; /* Pointer array declared */
static csparse Crt[CMAX];
static osparse Obj[OMAX];
static qtag *Romhead=0; /* Queue header and tail pointers */
static qtag *Romtail=0;
static qtag *Crthead=0;
static qtag *Crttail=0;
static qtag *Objhead=0;
static qtag *Objtail=0;
int Rsize=0; /* Queue sizes */
int Csize=0;
int Osize=0;
/**********************************************************************/
/* load_rom */
/**********************************************************************/
/* This function accepts a room number as its first argument and then */
/* returns a dblpointer to that room's data in the second parameter. */
/* If the room has already been loaded, the pointer is simply returned. */
/* Otherwise, the room is loaded into memory. If a maximal number of */
/* rooms is already in the memory, then the least recently used room */
/* is stored back to disk, and the memory is freed. */
int load_rom(index, rom_ptr)
int index;
room **rom_ptr;
{
int fd;
qtag *qt;
char file[256], filebak[256];
if(index >= RMAX || index < 0)
return(-1);
/* Check if room is already loaded, and if so return pointer */
if(Rom[index].rom) {
front_queue(&Rom[index].q_rom, &Romhead, &Romtail, &Rsize);
*rom_ptr = Rom[index].rom;
}
/* Otherwise load the room, store rooms if queue size becomes */
/* too big, and return a pointer to the newly loaded room */
else {
sprintf(file, "%s/r%05d", ROOMPATH, index);
fd = open(file, O_RDONLY, 0);
if(fd < 0)
return(-1);
*rom_ptr = (room *)malloc(sizeof(room));
if(!*rom_ptr)
merror("load_rom", FATAL);
if(read_rom(fd, *rom_ptr) < 0) {
close(fd);
return(-1);
}
close(fd);
(*rom_ptr)->rom_num = index;
qt = (qtag *)malloc(sizeof(qtag));
if(!qt)
merror("load_rom", FATAL);
qt->index = index;
Rom[index].rom = *rom_ptr;
Rom[index].q_rom = qt;
put_queue(&qt, &Romhead, &Romtail, &Rsize);
while(Rsize > RQMAX) {
pull_queue(&qt, &Romhead, &Romtail, &Rsize);
if(Rom[qt->index].rom->first_ply) {
put_queue(&qt, &Romhead, &Romtail, &Rsize);
continue;
}
sprintf(file, "%s/r%05d", ROOMPATH, qt->index);
sprintf(filebak, "%s~", file);
rename(file, filebak);
fd = open(file, O_RDWR | O_CREAT, ACC);
if(fd < 1)
return(-1);
if(!Rom[qt->index].rom)
merror("load_rom", NONFATAL);
if(write_rom(fd, Rom[qt->index].rom, PERMONLY) < 0) {
close(fd);
unlink(file);
rename(filebak, file);
merror("write_rom", NONFATAL);
return(-1);
}
close(fd);
unlink(filebak);
free_rom(Rom[qt->index].rom);
Rom[qt->index].rom = 0;
free(qt);
}
}
return(0);
}
int is_rom_loaded(num)
int num;
{
return(Rom[num].rom != 0);
}
/**********************************************************************/
/* reload_rom */
/**********************************************************************/
/* This function reloads a room from disk, if it's already loaded. This */
/* allows you to make changes to a room, and then reload it, even if it's */
/* already in the memory room queue. */
int reload_rom(num)
int num;
{
room *rom_ptr;
ctag *cp;
otag *op;
char file[80];
int fd;
if(!Rom[num].rom)
return(0);
sprintf(file, "%s/r%05d", ROOMPATH, num);
fd = open(file, O_RDONLY, 0);
if(fd < 0)
return(-1);
rom_ptr = (room *)malloc(sizeof(room));
if(!rom_ptr)
merror("reload_rom", FATAL);
if(read_rom(fd, rom_ptr) < 0) {
close(fd);
return(-1);
}
close(fd);
rom_ptr->first_ply = Rom[num].rom->first_ply;
Rom[num].rom->first_ply = 0;
add_permcrt_rom(rom_ptr);
if(!rom_ptr->first_mon) {
rom_ptr->first_mon = Rom[num].rom->first_mon;
Rom[num].rom->first_mon = 0;
}
if(!rom_ptr->first_obj) {
rom_ptr->first_obj = Rom[num].rom->first_obj;
Rom[num].rom->first_obj = 0;
}
free_rom(Rom[num].rom);
Rom[num].rom = rom_ptr;
cp = rom_ptr->first_ply;
while(cp) {
cp->crt->parent_rom = rom_ptr;
cp = cp->next_tag;
}
cp = rom_ptr->first_mon;
while(cp) {
cp->crt->parent_rom = rom_ptr;
cp = cp->next_tag;
}
op = rom_ptr->first_obj;
while(op) {
op->obj->parent_rom = rom_ptr;
op = op->next_tag;
}
return(0);
}
/**********************************************************************/
/* resave_rom */
/**********************************************************************/
/* This function saves an already-loaded room back to memory without */
/* altering its position on the queue. */
int resave_rom(num)
int num;
{
char file[256], filebak[256];
int fd;
if(!Rom[num].rom)
return(0);
sprintf(file, "%s/r%05d", ROOMPATH, num);
sprintf(filebak, "%s~", file);
rename(file, filebak);
fd = open(file, O_RDWR | O_CREAT, ACC);
if(fd < 1)
return(-1);
if(write_rom(fd, Rom[num].rom, PERMONLY) < 0) {
close(fd);
unlink(file);
rename(filebak, file);
return(-1);
}
close(fd);
unlink(filebak);
return(0);
}
/**********************************************************************/
/* resave_all_rom */
/**********************************************************************/
/* This function saves all memory-resident rooms back to disk. If the */
/* permonly parameter is non-zero, then only permanent items in those */
/* rooms are saved back. */
void resave_all_rom(permonly)
int permonly;
{
qtag *qt;
char file[80];
int fd;
qt = Romhead;
while(qt) {
if(!Rom[qt->index].rom) {
qt = qt->next;
continue;
}
sprintf(file, "%s/r%05d", ROOMPATH, qt->index);
fd = open(file, O_RDWR | O_CREAT, ACC);
if(fd < 1)
return;
if(write_rom(fd, Rom[qt->index].rom, permonly) < 0) {
close(fd);
return;
}
close(fd);
qt = qt->next;
}
}
/**********************************************************************/
/* save_all_ply */
/**********************************************************************/
/* This function saves all players currently in memory. */
void save_all_ply()
{
int i;
for(i=0; i<Tablesize; i++) {
if(Ply[i].ply && Ply[i].io && Ply[i].ply->name[0])
savegame(Ply[i].ply, 0);
}
}
/**********************************************************************/
/* flush_rom */
/**********************************************************************/
/* This function flushes out the room queue and clears the room sparse */
/* pointer array, without saving anything to file. It also clears all */
/* memory used by loaded rooms. Call this function before leaving the */
/* program. */
void flush_rom()
{
qtag *qt;
while(1) {
pull_queue(&qt, &Romhead, &Romtail, &Rsize);
if(!qt) break;
free_rom(Rom[qt->index].rom);
Rom[qt->index].rom = 0;
free(qt);
}
}
/**********************************************************************/
/* flush_crt */
/**********************************************************************/
/* This function flushes out the monster queue and clears the monster */
/* sparse pointer array without saving anything to file. It also */
/* clears all memory used by loaded creatures. Call this function */
/* before leaving the program. */
void flush_crt()
{
qtag *qt;
while(1) {
pull_queue(&qt, &Crthead, &Crttail, &Csize);
if(!qt) break;
free_crt(Crt[qt->index].crt);
Crt[qt->index].crt = 0;
free(qt);
}
}
/**********************************************************************/
/* flush_obj */
/**********************************************************************/
/* This function flushes out the object queue and clears the object */
/* sparse pointer array without saving anything to file. It also */
/* clears all memory used by loaded objects. Call this function */
/* leaving the program. */
void flush_obj()
{
qtag *qt;
while(1) {
pull_queue(&qt, &Objhead, &Objtail, &Osize);
if(!qt) break;
free_obj(Obj[qt->index].obj);
Obj[qt->index].obj = 0;
free(qt);
}
}
/**********************************************************************/
/* load_crt */
/**********************************************************************/
/* This function returns a pointer to the monster given by the index in */
/* the first parameter. The pointer is returned in the second. If the */
/* monster is already in memory, then a pointer is merely returned. */
/* Otherwise, the monster is loaded into memory and a pointer is re- */
/* turned. If there are too many monsters in memory, then the least */
/* recently used one is freed from memory. */
int load_crt(index, mon_ptr)
int index;
creature **mon_ptr;
{
int fd;
long n;
qtag *qt;
char file[256];
if(index >= CMAX || index < 0)
return(-1);
/* Check if monster is already loaded, and if so return pointer */
if(Crt[index].crt) {
front_queue(&Crt[index].q_crt, &Crthead, &Crttail, &Csize);
*mon_ptr = (creature *)malloc(sizeof(creature));
**mon_ptr = *Crt[index].crt;
}
/* Otherwise load the monster, erase monsters if queue size */
/* becomes too big, and return a pointer to the newly loaded monster */
else {
sprintf(file, "%s/m%02d", MONPATH, index/MFILESIZE);
fd = open(file, O_RDONLY, 0);
if(fd < 0) {
*mon_ptr = 0;
return(-1);
}
*mon_ptr = (creature *)malloc(sizeof(creature));
if(!*mon_ptr)
merror("load_crt", FATAL);
n = lseek(fd, (long)((index%MFILESIZE)*sizeof(creature)), 0);
if(n < 0L) {
free(*mon_ptr);
close(fd);
*mon_ptr = 0;
return(-1);
}
n = read(fd, *mon_ptr, sizeof(creature));
close(fd);
if(n < sizeof(creature)) {
free(*mon_ptr);
*mon_ptr = 0;
return(-1);
}
(*mon_ptr)->fd = -1;
qt = (qtag *)malloc(sizeof(qtag));
if(!qt)
merror("load_crt", FATAL);
qt->index = index;
Crt[index].crt = (creature *)malloc(sizeof(creature));
*Crt[index].crt = **mon_ptr;
Crt[index].q_crt = qt;
put_queue(&qt, &Crthead, &Crttail, &Csize);
while(Csize > CQMAX) {
pull_queue(&qt, &Crthead, &Crttail, &Csize);
free_crt(Crt[qt->index].crt);
Crt[qt->index].crt = 0;
free(qt);
}
}
(*mon_ptr)->lasttime[LT_HEALS].ltime = time(0);
(*mon_ptr)->lasttime[LT_HEALS].interval = 60L;
(*mon_ptr)->first_enm= 0;
return(0);
}
/**********************************************************************/
/* load_obj */
/**********************************************************************/
/* This function loads the object specified by the first parameter, and */
/* returns a pointer to it in the second parameter. If the object has */
/* already been loaded before, then a pointer is merely returned. */
/* Otherwise, the object is loaded into memory and the pointer is */
/* returned. If there are too many objects in memory, then the least */
/* recently used objects are freed from memory. */
int load_obj(index, obj_ptr)
int index;
object **obj_ptr;
{
int fd;
long n;
qtag *qt;
char file[256];
if(index >= OMAX || index < 0)
return(-1);
/* Check if object is already loaded, and if so return pointer */
if(Obj[index].obj) {
front_queue(&Obj[index].q_obj, &Objhead, &Objtail, &Osize);
*obj_ptr = (object *)malloc(sizeof(object));
**obj_ptr = *Obj[index].obj;
}
/* Otherwise load the object, erase objects if queue size */
/* becomes too big, and return a pointer to the newly loaded object */
else {
sprintf(file, "%s/o%02d", OBJPATH, index/OFILESIZE);
fd = open(file, O_RDONLY, 0);
if(fd < 0)
return(-1);
*obj_ptr = (object *)malloc(sizeof(object));
if(!*obj_ptr)
merror("load_obj", FATAL);
n = lseek(fd, (long)((index%OFILESIZE)*sizeof(object)), 0);
if(n < 0L) {
close(fd);
return(-1);
}
n = read(fd, *obj_ptr, sizeof(object));
close(fd);
if(n < sizeof(object))
return(-1);
qt = (qtag *)malloc(sizeof(qtag));
if(!qt)
merror("load_obj", FATAL);
qt->index = index;
Obj[index].obj = (object *)malloc(sizeof(object));
*Obj[index].obj = **obj_ptr;
Obj[index].q_obj = qt;
put_queue(&qt, &Objhead, &Objtail, &Osize);
while(Osize > OQMAX) {
pull_queue(&qt, &Objhead, &Objtail, &Osize);
free_obj(Obj[qt->index].obj);
Obj[qt->index].obj = 0;
free(qt);
}
}
return(0);
}
/***********************************************************************/
/* save_ply */
/***********************************************************************/
/* This function saves the player specified by the string in the first */
/* parameter, and uses the player in the second parameter. */
int save_ply(str, ply_ptr)
char *str;
creature *ply_ptr;
{
char file[256], filebak[256];
int fd, n;
#ifdef COMPRESS
char *a_buf, *b_buf;
int size;
#endif
sprintf(file, "%s/%s", PLAYERPATH, str);
sprintf(filebak, "%s~", file);
rename(file, filebak);
fd = open(file, O_RDWR | O_CREAT, ACC);
if(fd < 0) {
rename(filebak, file);
return(-1);
}
#ifdef COMPRESS
a_buf = (char *)malloc(100000);
if(!a_buf) merror("Memory allocation", FATAL);
n = write_crt_to_mem(a_buf, ply_ptr, 0);
if(n > 100000) merror(ply_ptr->name, FATAL);
b_buf = (char *)malloc(n);
if(!b_buf) merror("Memory allocation", FATAL);
size = compress(a_buf, b_buf, n);
n = write(fd, b_buf, size);
free(a_buf);
free(b_buf);
#else
n = write_crt(fd, ply_ptr, 0);
if(n < 0) {
close(fd);
unlink(file);
rename(filebak, file);
return(-1);
}
#endif
close(fd);
unlink(filebak);
return(0);
}
/***********************************************************************/
/* load_ply */
/***********************************************************************/
/* This function loads the player specified by the string in the first */
/* parameter, and returns the player in the second parameter. */
int load_ply(str, ply_ptr)
char *str;
creature **ply_ptr;
{
char file[80];
int fd, n;
#ifdef COMPRESS
char *a_buf, *b_buf;
int size;
#endif
sprintf(file, "%s/%s", PLAYERPATH, str);
fd = open(file, O_RDONLY, 0);
if(fd < 0)
return(-1);
*ply_ptr = (creature *)malloc(sizeof(creature));
if(!*ply_ptr)
merror("load_ply", FATAL);
#ifdef COMPRESS
a_buf = (char *)malloc(50000);
if(!a_buf) merror("Memory allocation", FATAL);
size = read(fd, a_buf, 50000);
if(size >= 50000) merror("Player too large", FATAL);
if(size < 1) {
close(fd);
return(-1);
}
b_buf = (char *)malloc(100000);
if(!b_buf) merror("Memory allocation", FATAL);
n = uncompress(a_buf, b_buf, size);
if(n > 100000) merror("Player too large", FATAL);
n = read_crt_from_mem(b_buf, *ply_ptr, 0);
free(a_buf);
free(b_buf);
#else
n = read_crt(fd, *ply_ptr);
if(n < 0) {
close(fd);
return(-1);
}
#endif
close(fd);
return(0);
}
/**********************************************************************/
/* put_queue */
/**********************************************************************/
/* put_queue places the queue tag pointed to by the first paramater onto */
/* a queue whose head and tail tag pointers are the second and third */
/* parameters. If parameters 2 & 3 are 0, then a new queue is created. */
/* The fourth parameter points to a queue size counter which is */
/* incremented. */
void put_queue(qt, headptr, tailptr, sizeptr)
qtag **qt;
qtag **headptr;
qtag **tailptr;
int *sizeptr;
{
*sizeptr = *sizeptr + 1;
if(!*headptr) {
*headptr = *qt;
*tailptr = *qt;
(*qt)->next = 0;
(*qt)->prev = 0;
}
else {
(*headptr)->prev = *qt;
(*qt)->next = *headptr;
(*qt)->prev = 0;
*headptr = *qt;
}
}
/**********************************************************************/
/* pull_queue */
/**********************************************************************/
/* pull_queue removes the last queue tag on the queue specified by the */
/* second and third parameters and returns that tag in the first */
/* parameter. The fourth parameter points to a queue size counter */
/* which is decremented. */
void pull_queue(qt, headptr, tailptr, sizeptr)
qtag **qt;
qtag **headptr;
qtag **tailptr;
int *sizeptr;
{
if(!*tailptr)
*qt = 0;
else {
*sizeptr = *sizeptr - 1;
*qt = *tailptr;
if((*qt)->prev) {
(*qt)->prev->next = 0;
*tailptr = (*qt)->prev;
}
else {
*headptr = 0;
*tailptr = 0;
}
}
}
/**********************************************************************/
/* front_queue */
/**********************************************************************/
/* front_queue removes the queue tag pointed to by the first parameter */
/* from the queue (specified by the second and third parameters) and */
/* places it back at the head of the queue. The fourth parameter is a */
/* pointer to a queue size counter, and it remains unchanged. */
void front_queue(qt, headptr, tailptr, sizeptr)
qtag **qt;
qtag **headptr;
qtag **tailptr;
int *sizeptr;
{
if((*qt)->prev) {
((*qt)->prev)->next = (*qt)->next;
if(*qt == *tailptr)
*tailptr = (*qt)->prev;
}
if((*qt)->next) {
((*qt)->next)->prev = (*qt)->prev;
if(*qt == *headptr)
*headptr = (*qt)->next;
}
if(!(*qt)->prev && !(*qt)->next) {
*headptr = 0;
*tailptr = 0;
}
(*qt)->next = 0;
(*qt)->prev = 0;
*sizeptr = *sizeptr - 1;
put_queue(qt, headptr, tailptr, sizeptr);
}